<?php
declare (strict_types = 1);

namespace app\middleware;

use app\model\Admin;
use think\Response;

/**
 * 权限验证中间件
 * Class Permission
 * @package app\middleware
 */
class Permission
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // 检查是否是OPTIONS预检请求，如果是则跳过验证
        if ($request->method() === 'OPTIONS') {
            return $next($request);
        }
        
        // 获取当前管理员ID（由Auth中间件设置）
        $adminId = $request->adminId ?? null;
        if (!$adminId) {
            return json([
                'code' => 401,
                'message' => '请先登录',
                'data' => null
            ], 401);
        }
        
        // 获取当前请求的路径和方法
        $path = $request->pathinfo();
        $method = strtoupper($request->method());
        
        // 生成权限代码（基于路径和方法）
        $permissionCode = $this->generatePermissionCode($path, $method);
        
        // 获取管理员
        $admin = Admin::find($adminId);
        if (!$admin) {
            return json([
                'code' => 401,
                'message' => '用户不存在',
                'data' => null
            ], 401);
        }
        
        // 获取管理员权限
        $permissions = $admin->getPermissions();
        
        // 检查是否有对应权限
        if (!in_array($permissionCode, $permissions)) {
            \think\facade\Log::info('权限验证失败 - 用户ID: ' . $adminId . ', 请求路径: ' . $path . ', 权限代码: ' . $permissionCode . ', 用户权限: ' . json_encode($permissions));
            
            return json([
                'code' => 403,
                'message' => '没有权限访问该接口',
                'data' => null
            ], 403);
        }
        
        \think\facade\Log::info('权限验证通过 - 用户ID: ' . $adminId . ', 权限代码: ' . $permissionCode);
        
        return $next($request);
    }
    
    /**
     * 根据路径和方法生成权限代码
     * @param string $path
     * @param string $method
     * @return string
     */
    private function generatePermissionCode(string $path, string $method): string
    {
        // 移除api前缀
        $path = preg_replace('/^api\//', '', $path);
        
        // 权限代码映射规则
        $permissionMap = [
            // 管理员管理
            'GET:admins' => 'admin:list',
            'GET:admins/(\d+)' => 'admin:read',
            'POST:admins' => 'admin:create',
            'PUT:admins/(\d+)' => 'admin:update',
            'DELETE:admins/(\d+)' => 'admin:delete',
            'DELETE:admins' => 'admin:batch_delete',
            'PATCH:admins/(\d+)/status' => 'admin:change_status',
            
            // 角色管理
            'GET:roles' => 'role:list',
            'GET:roles/all' => 'role:list',
            'GET:roles/(\d+)' => 'role:read',
            'POST:roles' => 'role:create',
            'PUT:roles/(\d+)' => 'role:update',
            'DELETE:roles/(\d+)' => 'role:delete',
            'DELETE:roles' => 'role:batch_delete',
            'PATCH:roles/(\d+)/status' => 'role:change_status',
            
            // 角色权限管理
            'GET:roles/(\d+)/permissions' => 'role:permission:read',
            'PUT:roles/(\d+)/permissions' => 'role:permission:update',
            
            // 权限管理
            'GET:permissions' => 'permission:list',
            'GET:permissions/tree' => 'permission:tree',
            'GET:permissions/(\d+)' => 'permission:read',
            'POST:permissions' => 'permission:create',
            'PUT:permissions/(\d+)' => 'permission:update',
            'DELETE:permissions/(\d+)' => 'permission:delete',
            'DELETE:permissions' => 'permission:batch_delete',
            'PATCH:permissions/(\d+)/status' => 'permission:change_status',
            
            // 菜单管理
            'GET:menus' => 'menu:list',
            'GET:menus/tree' => 'menu:tree',
            'GET:menus/router' => 'menu:router',
            'GET:menus/(\d+)' => 'menu:read',
            'POST:menus' => 'menu:create',
            'PUT:menus/(\d+)' => 'menu:update',
            'DELETE:menus/(\d+)' => 'menu:delete',
            'DELETE:menus' => 'menu:batch_delete',
            'PATCH:menus/(\d+)/status' => 'menu:change_status',
        ];
        
        $requestKey = $method . ':' . $path;
        
        // 精确匹配
        if (isset($permissionMap[$requestKey])) {
            return $permissionMap[$requestKey];
        }
        
        // 正则匹配
        foreach ($permissionMap as $pattern => $permission) {
            if (preg_match('/^' . str_replace('/', '\/', $pattern) . '$/', $requestKey)) {
                return $permission;
            }
        }
        
        // 如果没有匹配到，返回默认权限代码
        return str_replace(['/', ':'], [':', ':'], $path) . ':' . strtolower($method);
    }
}